//
//  HelloWorldLayer.m
//  BeatPong
//
//  Created by Gabriel Lumbi on 12-08-16.
//  Copyright __MyCompanyName__ 2012. All rights reserved.
//


// Import the interfaces
#import "GameLayer.h"

// Needed to obtain the Navigation Controller
#import "AppDelegate.h"
#import "Ball.h"
#import "Paddle.h"
#import "PaddleHitEffect.h"
#import "WallHitEffect.h"

#pragma mark - GameLayer

// HelloWorldLayer implementation
@implementation GameLayer

float currentBallSpeed = 0.f;
#undef RAND_MAX
#define RAND_MAX 1000

#pragma mark -
#pragma mark Life Cycle

// Helper class method that creates a Scene with the HelloWorldLayer as the only child.
+(CCScene *) scene
{
	CCScene *scene = [CCScene node]; //is an autorelease object
	GameLayer *layer = [GameLayer node]; //is an autorelease object
	[scene addChild: layer];
	return scene;
}

-(id) init
{
	if( (self=[super init]) ) {
        screenSize = self.boundingBox.size;
        screenDiagonalSquared = screenSize.width * screenSize.width + screenSize.height * screenSize.height;
        
        enemyColor = ccc4f(1,0,0,1);
        allyColor = ccc4f(0, 1, 0, 1);
        neutralColor = ccc4f(1, 0, 1, 1);
        
        otherPaddle = [Paddle new];
        yourPaddle = [Paddle new];
        
        otherPaddle.position = ccp(screenSize.width/2.f, screenSize.height - 50);
        otherPaddle.color = enemyColor;
        
        yourPaddle.position = ccp(otherPaddle.position.x, 50);
        yourPaddle.color = allyColor;
        
        [self addChild:yourPaddle];
        [self addChild:otherPaddle];
        
        ball = [Ball new];
        
        [self resetBall];
        [self addChild: ball];
        
        paddleHitEffects = [[NSArray alloc] initWithObjects:
                            [[PaddleHitEffect alloc] init],
                            [[PaddleHitEffect alloc] init],
                            [[PaddleHitEffect alloc] init],
                            nil];
        
        for(PaddleHitEffect* p in paddleHitEffects){
            [self addChild:p];
        }
        
        wallHitEffects = [[NSArray alloc] initWithObjects:
                          [[WallHitEffect alloc] init],
                          [[WallHitEffect alloc] init],
                          [[WallHitEffect alloc] init],
                          nil];
        
        for(WallHitEffect* w in wallHitEffects){
            [self addChild:w];
        }
        
        lblAllyScore = [CCLabelTTF labelWithString:@"0" fontName:@"Arial" fontSize:20];
        lblAllyScore.position = ccp(50, 50);
        lblEnemyScore = [CCLabelTTF labelWithString:@"0" fontName:@"Arial" fontSize:20];
        lblEnemyScore.position = ccp(screenSize.width - 50, screenSize.height - 50);
        
        [self addChild: lblAllyScore];
        [self addChild: lblEnemyScore];
        
        self.isTouchEnabled = YES;
        
        [self scheduleUpdate];
	}
	return self;
}

-(void) dealloc
{
    [otherPaddle release];
    [yourPaddle release];
    [ball release];
    [paddleHitEffects release];
    [wallHitEffects release];
    
    [super dealloc];
}

#pragma mark -

#pragma mark Draw

-(void) draw
{
    [super draw];
    
    float sineSquaredOfTime = tanf(currentTime);
    
    for(int i=0; i<screenSize.height; i+=10){
        float intensity = (1-abs(screenSize.height*sineSquaredOfTime-i)/screenSize.height);
        ccDrawColor4F(intensity, 0.2f, 0.2f, 1);
        for(int j=0; j<screenSize.width; j+=10){
            ccDrawPoint(ccp(j,i));
        }
    }
   
    ccDrawColor4F(neutralColor.r, neutralColor.g, neutralColor.b, neutralColor.a);
    ccDrawCircle(ccp(screenSize.width/2.f, screenSize.height/2.f), 30, 0, 10, NO);
    
    //Boundaries
    
    ccDrawLine(ccp(0,0), ccp(0, screenSize.height));
    ccDrawLine(ccp(0,0), ccp(screenSize.width, 0));
    ccDrawLine(ccp(0,screenSize.height), ccp(screenSize.width, screenSize.height));
    ccDrawLine(ccp(screenSize.width, screenSize.height), ccp(screenSize.width, 0));
}

#pragma mark -
#pragma mark Update

-(void) update: (ccTime)deltaTime
{
    currentTime += deltaTime;
    
    //Ball is out
    if(ball.position.y + ball.radius <= 0){
        [self resetBall];
        enemyScore += 1;
        lblEnemyScore.string = [NSString stringWithFormat:@"%d",enemyScore];
    }else if(ball.position.y - ball.radius >= screenSize.height){
        [self resetBall];
        allyScore += 1;
        lblAllyScore.string = [NSString stringWithFormat:@"%d",allyScore];
    }
    
    //Bounds collisions
    if(ball.position.x - ball.radius <= 0)
    {
        ball.velocity = ccp(abs(ball.velocity.x), ball.velocity.y);
        
        WallHitEffect* wallHitEffect = [self findFreeWallHitEffect];
        if(wallHitEffect)
        {
            wallHitEffect.position = ccp(ball.position.x - ball.radius, ball.position.y);
            wallHitEffect.xDisplacement = abs(wallHitEffect.xDisplacement); //TODO: Fix me
            [wallHitEffect play];
        }
        
    }else if(ball.position.x + ball.radius >= screenSize.width)
    {
        ball.velocity = ccp(-abs(ball.velocity.x), ball.velocity.y);
        
        WallHitEffect* wallHitEffect = [self findFreeWallHitEffect];
        if(wallHitEffect)
        {
            wallHitEffect.position = ccp(ball.position.x + ball.radius, ball.position.y);
            wallHitEffect.xDisplacement = -abs(wallHitEffect.xDisplacement); //TODO: Fix me
            [wallHitEffect play];
        }
    }
    
    //Your paddle collision
    if(ball.position.x > yourPaddle.position.x - yourPaddle.width/2 &&
       ball.position.x < yourPaddle.position.x + yourPaddle.width/2)
    {
        //TODO fix me
        if(ball.position.y - ball.radius <= yourPaddle.position.y + yourPaddle.height/2 &&
           ball.position.y - ball.radius > yourPaddle.position.y - yourPaddle.height/2)
        {
            //Apply paddle bounce effect
            float xDistFromBallToPaddle = ball.position.x - yourPaddle.position.x;
            float xRelDistFromBallToPaddle = xDistFromBallToPaddle / (yourPaddle.width * 0.5);
            
            float xDesiredVelocity = currentBallSpeed * xRelDistFromBallToPaddle;
            float yDesiredVelocity = sqrtf(powf(currentBallSpeed,2) - powf(xDesiredVelocity, 2));
            
            ball.velocity = ccp(xDesiredVelocity, yDesiredVelocity);
            
            PaddleHitEffect* paddleHitEffect = [self findFreePaddleHitEffect];
            if(paddleHitEffect)
            {
                paddleHitEffect.position = ccp(ball.position.x, ball.position.y-ball.radius);
                [paddleHitEffect play];
            }
        }
    }
    
    //Other paddle collision
    if(ball.position.y + ball.radius > otherPaddle.position.y - otherPaddle.height/2)
    {
        ball.velocity = ccp(ball.velocity.x, -abs(ball.velocity.y));
    }
    
    //Cheater bot
    if(ball.position.y > 0)
    {
        otherPaddle.position = ccp(ball.position.x, otherPaddle.position.y);
    }
}

#pragma mark -
#pragma mark Touch

-(void) registerWithTouchDispatcher
{
    [[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
    return YES;
}

-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
    CGPoint touchPosition = [self convertTouchToNodeSpace:touch];
    yourPaddle.position = ccp(touchPosition.x, yourPaddle.position.y);
}

#pragma mark -
#pragma mark Methods

-(PaddleHitEffect*) findFreePaddleHitEffect
{
    for(PaddleHitEffect* p in paddleHitEffects){
        if(p.over){
            return p;
        }
    }
    return nil;
}

-(WallHitEffect*) findFreeWallHitEffect
{
    for(WallHitEffect* w in wallHitEffects){
        if(w.over){
            return w;
        }
    }
    return nil;
}

-(void) resetBall
{
    ball.position = ccp(screenSize.width/2.f, screenSize.height/2.f);
    float rnd = rand() / (float)RAND_MAX;
    float rndRad = rnd * M_2_PI;
    //prevent stall
    if(rndRad == 0 || rndRad == M_PI){
        rndRad += M_PI_4;
    }
    
    currentBallSpeed = 283; //sqrt(200*200+200*200)
    ball.velocity = ccp(200,200);
    ball.velocity = ccp(currentBallSpeed * cosf(rndRad), currentBallSpeed * sinf(rndRad));
    ball.color = neutralColor;
}

@end